added samples
[windows-sources.git] / sdk / samples / all in on code / Visual Studio 2008 / ATLShellExtDragAndDropHandler / FileDragAndDropExt.cpp
blobbc1afbac457f436af0fc9a4bad64a520f1dffff3
1 /****************************** Module Header ******************************\
2 * Module Name: FileDragAndDropExt.cpp
3 * Project: ATLShellExtDragAndDropHandler
4 * Copyright (c) Microsoft Corporation.
5 *
6 * FileDragAndDropExt is an example of drag-and-drop handler for file objects.
7 * After the setup of the handler, when you right-click any files to drag the
8 * files to a directory or the desktop, a context menu with "All-In-One Code
9 * Framework" menu item will be displayed. Clicking the menu item prompts a
10 * message box that shows the files being dragged and the target location that
11 * the files are dropped to.
13 * This source is subject to the Microsoft Public License.
14 * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
15 * All other rights reserved.
17 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
18 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
20 \***************************************************************************/
22 #pragma region Includes
23 #include "stdafx.h"
24 #include "FileDragAndDropExt.h"
25 #pragma endregion
28 /////////////////////////////////////////////////////////////////////////////
29 // CFileDragAndDropExt IShellExtInit methods.
30 //
33 // FUNCTION: CFileDragAndDropExt::Initialize(LPCITEMIDLIST, LPDATAOBJECT,
34 // HKEY)
36 // PURPOSE: Initializes a property sheet extension, shortcut menu extension,
37 // or drag-and-drop handler.
39 IFACEMETHODIMP CFileDragAndDropExt::Initialize(
40 LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID)
42 // Get the name of the directory where the files were dropped
43 if (!SHGetPathFromIDList(pidlFolder, m_szFolderDroppedIn))
44 return E_FAIL;
46 // Get a list of all the objects that were dropped
48 if (NULL == pDataObj)
50 return E_INVALIDARG;
53 FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
54 STGMEDIUM stm;
56 // pDataObj contains the objects being acted upon. In this example,
57 // we get an HDROP handle for enumerating the selected files.
58 if (FAILED(pDataObj->GetData(&fe, &stm)))
59 return E_INVALIDARG;
61 // Get an HDROP handle.
62 HDROP hDrop = (HDROP)GlobalLock(stm.hGlobal);
63 if (NULL == hDrop)
65 ReleaseStgMedium(&stm);
66 return E_INVALIDARG;
69 // Determine how many files are involved in this operation
70 UINT nFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
71 if (nFiles == 0)
73 GlobalUnlock(stm.hGlobal);
74 ReleaseStgMedium(&stm);
75 return E_INVALIDARG;
78 // Enumerates through the selected files and directories
79 TCHAR szFileName[MAX_PATH];
80 for (UINT i = 0; i < nFiles; i++)
82 // Get the next filename
83 if (0 == DragQueryFile(hDrop, i, szFileName, MAX_PATH))
84 continue;
86 m_lsFiles.push_back(szFileName);
89 // Release resources
90 GlobalUnlock(stm.hGlobal);
91 ReleaseStgMedium(&stm);
93 // If we found any files we can work with, return S_OK. Otherwise return
94 // E_INVALIDARG so we don't get called again for this drag-and-drop
95 // operation.
96 return (m_lsFiles.size() > 0) ? S_OK : E_INVALIDARG;
100 /////////////////////////////////////////////////////////////////////////////
101 // CFileDragAndDropExt IContextMenu methods.
104 #define IDM_SAMPLE 0 // The command's identifier offset.
108 // FUNCTION: CFileContextMenuExt::OnSample(HWND)
110 // PURPOSE: OnSample handles the "Sample" verb of the shell extension.
112 void CFileDragAndDropExt::OnSample(HWND hWnd)
114 // Concat the dragged files to a string
115 DWORD dwBufferSize = m_lsFiles.size() * MAX_PATH;
116 TCHAR* pszFiles = new TCHAR[dwBufferSize];
117 ZeroMemory(pszFiles, dwBufferSize);
119 string_list::const_iterator end;
120 for (string_list::const_iterator it = m_lsFiles.begin(),
121 end = m_lsFiles.end();
122 it != end; it++)
124 _tcscat_s(pszFiles, dwBufferSize, it->c_str());
125 _tcscat_s(pszFiles, dwBufferSize, _T("\n"));
128 TCHAR* pszMessage = new TCHAR[512 + dwBufferSize];
129 _stprintf_s(pszMessage, 512 + dwBufferSize, _T("Drag-and-drop handler") \
130 _T("\n\nSource file(s):\n%s\nTarge location:\n%s"), pszFiles,
131 m_szFolderDroppedIn);
133 MessageBox(hWnd, pszMessage, _T("ATLShellExtDragAndDropHandler"),
134 MB_ICONINFORMATION);
136 delete[] pszFiles;
137 delete[] pszMessage;
142 // FUNCTION: CFileDragAndDropExt::QueryContextMenu(HMENU, UINT, UINT, UINT,
143 // UINT)
145 // PURPOSE: The Shell calls IContextMenu::QueryContextMenu to allow the
146 // context menu handler to add its menu items to the menu. It
147 // passes in the HMENU handle in the hmenu parameter. The
148 // indexMenu parameter is set to the index to be used for the
149 // first menu item that is to be added.
151 IFACEMETHODIMP CFileDragAndDropExt::QueryContextMenu(
152 HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
154 // If uFlags include CMF_DEFAULTONLY then we should not do anything
155 if (CMF_DEFAULTONLY & uFlags)
157 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
160 // Use either InsertMenu or InsertMenuItem to add menu items to the list
161 InsertMenu(hMenu, indexMenu, MF_STRING | MF_BYPOSITION, idCmdFirst +
162 IDM_SAMPLE, _T("&All-In-One Code Framework"));
164 // Return an HRESULT value with the severity set to SEVERITY_SUCCESS.
165 // Set the code value to the offset of the largest command identifier
166 // that was assigned, plus one (1)
167 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_SAMPLE + 1));
172 // FUNCTION: CFileDragAndDropExt::InvokeCommand(LPCMINVOKECOMMANDINFO)
174 // PURPOSE: This method is called when a user clicks a menu item to tell
175 // the handler to run the associated command. The lpcmi parameter
176 // points to a structure that contains the needed information.
178 IFACEMETHODIMP CFileDragAndDropExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
180 // The high-word of lpcmi->lpVerb must be NULL because we did not
181 // implement IContextMenu::GetCommandString to specify any verb for the
182 // command
183 if (NULL != HIWORD(lpcmi->lpVerb))
185 return E_INVALIDARG;
188 // Then, the low-word of lpcmi->lpVerb should contain the command's
189 // identifier offset
190 if (LOWORD(lpcmi->lpVerb) == IDM_SAMPLE)
192 OnSample(lpcmi->hwnd);
194 else
196 // If the verb is not recognized by the drag-and-drop handler, it
197 // must return E_FAIL to allow it to be passed on to the other
198 // drag-and-drop handlers that might implement that verb.
199 return E_FAIL;
202 return S_OK;